package com.kt.emall.product;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

/**
 * 1、整合Mybatis-plus
 *      1）、导入依赖
 *      2）、配置
 *          1、配置数据源
 *              1）、导入数据库的驱动
 *              2）、配置数据源
 *          2、配置Mybatis-Plus
 *              1）、使用@MapperScan
 *              2）、告诉Mybatis-Plus，sql映射文件位置
 *
 * 2、逻辑删除
 *      1）、配置全局的逻辑删除规则（可省略）
 *      2）、配置删除的组件Bean（Mybatis-Plus3.1.1开始可省略）
 *      3）、给Bean加上逻辑删除注解@TableLogic
 *
 * 3、JSR303数据校验
 *      1）、给bean中添加校验注解：@NotNull、@NotEntity、@NotBlank，并定义自己的message提示
 *      2）、开启校验功能（在需要校验的功能上也就是Controller中的某个方法参数中添加@Valid注解）
 *      3）、给校验的Controller后面紧跟一个@BindingResult注解，就可以获取校验的结果
 *      4）、分组校验（多场景的复杂校验）
 *          1）、给校验注解标注什么情况需要进行校验
 *          @NotBlank(message = "品牌名必须提交", groups = {UpdateGroup.class, AddGroup.class})
 *          2）、在Controller中对应方法中添加@Validated({AddGroup.class})
 *          3）、默认没有指定分组的校验注解，在有分组校验情况下不生效
 *      5）、自定义校验
 *          1）、编写一个自定义的校验注解 ListValue
 *          2）、编写一个自定义的校验器 ListValueConstraintValidator
 *          3）、关联自定义的校验注解和自定义的校验器 @Constraint(validatedBy = {ListValueConstraintValidator.class}),这里可以指定多个不同的校验器，以适配不同类型的校验
 *
 * 4、统一异常处理@ControllerAdvice
 *      1）、编写异常处理类，使用@ControllerAdvice
 *      2）、使用@ExceptionHandler标注方法可以处理的异常
 *
 * 5、模板引擎
 *      1）、thymeleaf-starter：关闭缓存
 *      2）、静态资源都放在static文件下就可以按照路劲直接访问
 *      3）、页面放在template下，直接访问
 *          spring boot，访问项目的时候，默认会找index
 *      4）、页面修改不重启服务器实时更新
 *          1）、引入dev-tools
 *          2）、修改完页面 controller shift F9 重新自动编译下页面，代码配置推荐重启
 *
 * 6、整合redis
 *      1）、引入data-redis-starter
 *      2）、简单配置redis的host等信息
 *      3）、使用spring boot自动配置好的StringRedTemplate来操作redis
 *
 * 7、整合redisson作为分布式锁等功能框架
 *      1）、导入依赖
 *      2）、配置redisson
 *
 * 8、整合SpringCache简化开发
 *      1）、引入依赖redis、cache
 *      2）、写配置
 *          （1）、自动配置了哪些
 *          CacheAutoConfiguration会导入RedisCacheConfiguration
 *          自动配好了缓存管理器RedisCacheManger
 *          （2）、配置使用Redis作为缓存
 *      3）、测试使用缓存
 *          （1）、开启缓存功能 @EnableCaching
 *          （2）、只需要使用注解就能完成缓存操作
 *      4）、原理：
 *          CacheAutoConfiguration -> RedisCacheConfiguration ->RedisCacheManager -> 初始化所有缓存 -> 每个缓存决定使用什么配置 -> 如果RedisCacheConfiguration有就用自己的，没有就用默认配置 -> 想改缓存配置，只需要给容器中放一个RedisCacheConfiguration即可 -> 就会应用到当前RedisCacheManager管理的所有缓存分区中
 *      5）、Spring-Cache不足：
 *          （1）、读模式：
 *              缓存穿透：查询一个null数据。解决：缓存空数据；cache-null-values: true
 *              缓存击穿：大量并发进来同时查询一个正好过期的数据。解决：加锁；？默认是无加锁的；sync=true(加锁，解决击穿)
 *              缓存雪崩：大量key同时过期。解决：加随机时间。加上过期时间；time-to-live: 3600000
 *          （2）、写模式（缓存与数据库一致）
 *              读写加锁。
 *              引入Canal，感知到MySQL的更新去更新数据库
 *              读多写多，直接去数据库查询
 *      总结：常规数据（读多写少，即时性，一致性要求不高的数据）；完全可以使用Spring-Cache；学模式(只要缓存的数据有过期时间就足够了)
 *           特殊数据：特殊设计
 *      原理：
 *          CacheManager(RedisCacheManager)->Cache(RedisCache)->Cache负责缓存的读写
 *
 */
@EnableRedisHttpSession
@EnableFeignClients(basePackages = "com.kt.emall.product.feign")
@EnableDiscoveryClient
@MapperScan("com.kt.emall.product.dao")
@SpringBootApplication
public class EmallProductApplication {

    public static void main(String[] args) {
        SpringApplication.run(EmallProductApplication.class, args);
    }

}
